﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "RevisionCloudStyleDialog.h"

#include <QMessageBox>

#include "GmStyleSheetHelper.h"
#include "IRevisionCloudStyleManager.h"
#include "IGraphicsStyle.h"
#include "IElementBasicInformation.h"
#include "IUserTransaction.h"
#include "IGenericElement.h"
#include "IRevisionCloud.h"
#include "GbmpQuickCast.h"
#include "GbmpDocUtils.h"
#include "StringUtil.h"

#include "ISelection.h"
#include "ContainerUtil.h"
#include "IGraphicsNodeReference.h"

#include "IGenericType.h"
#include "ICopyOperator.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;

RevisionCloudStyleDlg::RevisionCloudStyleDlg(gcmp::IDocument*pDoc, const gcmp::ElementId& revCloudId, QWidget *parent /*= 0*/):m_pDocument(pDoc), QDialog(parent, Qt::FramelessWindowHint)
{
    m_ui.setupUi(this);

    QPixmap picAdd(QStringLiteral(":/images/type_add.png"));
    m_ui.TypeAdd->setIconSize(QSize(picAdd.width(), picAdd.height()));
    m_ui.TypeAdd->setIcon(picAdd);
    //setFixedSize(404, 360);

    // Style
    std::wstring styleSheetStr = GmStyleSheetHelper::Instance()->GetCurrentStyleData();
    setStyleSheet(QString::fromStdWString(styleSheetStr));

    // Title
    m_ui.gbmp_title->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
    m_ui.gbmp_title->setIconVisible(false);
    m_ui.gbmp_title->setMaxButtonVisible(false);
    m_ui.gbmp_title->setMinButtonVisible(false);
    m_ui.gbmp_title->setText(QString::fromStdWString(GBMP_TR(L"类型参数")));
    this->setProperty("use_gbmp_title", true);

    connect(m_ui.gbmp_title, &GmTitleBar::closeRequested, this, &RevisionCloudStyleDlg::reject);
    connect(m_ui.gbmp_title, &GmTitleBar::moveRequested, this, &RevisionCloudStyleDlg::onMoveRequested);

    
    connect(m_ui.pushButtonOk, SIGNAL(clicked()), this, SLOT(ClickOkButton()));
    connect(m_ui.pushButtonCancel, SIGNAL(clicked()), this, SLOT(ClickCancelButton()));
    InitStyles();
    connect(m_ui.comboBoxType, &QComboBox::currentTextChanged, this, &RevisionCloudStyleDlg::onTypeChanged);

    connect(m_ui.pushButtonOkSelect, SIGNAL(clicked()), this, SLOT(ClickOkButtonSelect()));
    connect(m_ui.pushButtonCancelSelect, SIGNAL(clicked()), this, SLOT(ClickCancelButtonSelect()));
    connect(m_ui.TypeAdd, SIGNAL(clicked()), this, SLOT(OnComponentTypeAddButtonClick()));

    InitSetElementType(pDoc);
}

RevisionCloudStyleDlg::~RevisionCloudStyleDlg()
{

}

void RevisionCloudStyleDlg::onMoveRequested(const QPoint& cursorPos, const QPoint& offset)
{
    Q_UNUSED(cursorPos);
    move(pos() + offset);
}

static double GetCharHeightFromName(const std::wstring& sStyleName)
{
    std::size_t nStart = sStyleName.find(L"-", 0);
    std::size_t nEnd = sStyleName.find(L"-", nStart + 1);
    std::wstring sValue = sStyleName.substr(nStart + 1, nEnd - nStart - 1);
    return gcmp::StringUtil::ToNumber<double>(sValue);
}

void RevisionCloudStyleDlg::ClickOkButton()
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pDocument != nullptr, L"文档为空",L"GDMPLab",L"2024-03-30");
    

    gcmp::IRevisionCloudStyleManager* pStyleMgr = gcmp::IRevisionCloudStyleManager::Get(m_pDocument);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pStyleMgr != nullptr, L"云线的样式管理为空",L"GDMPLab",L"2024-03-30");

    gcmp::OwnerPtr<gcmp::IUserTransaction> opUserTans = gcmp::IUserTransaction::Create(m_pDocument, L"修改云线样式");
    DBG_WARN_AND_RETURN_VOID_UNLESS(opUserTans != nullptr, L"事务创建为空",L"GDMPLab",L"2024-03-30");

    pStyleMgr->SetCurrentStyleType(m_ui.comboBoxType->currentText().toStdWString());
    pStyleMgr->UpdateVersionStyle(m_ui.lineEditVersion->text().toStdWString());
    pStyleMgr->UpdateAnnotationStype(m_ui.lineEditAnnatation->text().toStdWString());
    opUserTans->Commit();

    QDialog::accept();
}

void RevisionCloudStyleDlg::ClickCancelButton()
{
    QDialog::reject();

}

void RevisionCloudStyleDlg::ClickOkButtonSelect()
{
    gcmp::OwnerPtr<gcmp::IUserTransaction> opUserTans = gcmp::IUserTransaction::Create(m_pDocument, L"修改选中对象的云线样式");
    DBG_WARN_AND_RETURN_VOID_UNLESS(opUserTans != nullptr, L"事务创建为空",L"GDMPLab",L"2024-03-30");

    onChangeTypeOfSelectedElement(m_ui.comboBoxTypeSelect->currentText());

    opUserTans->Commit();

    QDialog::accept();
}

void RevisionCloudStyleDlg::ClickCancelButtonSelect()
{
    QDialog::reject();

}

void RevisionCloudStyleDlg::onTypeChanged(const QString & strText)
{
    gcmp::IRevisionCloudStyleManager* pStyleMgr = gcmp::IRevisionCloudStyleManager::Get(m_pDocument);

    gcmp::RevisionCloudStyleData data = pStyleMgr->GetStyleTypeData(strText.toStdWString());
    m_ui.lineEditLoop->setText(QString::fromStdWString(data.LoopStyle));
    m_ui.lineEditAnnatation->setText(QString::fromStdWString(data.AnnotationTextStyle));
    m_ui.lineEditVersion->setText(QString::fromStdWString(data.VersionTextStyle));
    m_ui.lineEditLinewire->setText(QString::fromStdWString(data.LeadWireStyle));

}

void RevisionCloudStyleDlg::onChangeTypeOfSelectedElement(const QString & strText)
{
    gcmp::IRevisionCloudStyleManager* pStyleMgr = gcmp::IRevisionCloudStyleManager::Get(m_pDocument);
    ElementId typeId = pStyleMgr->FindStyleType(strText.toStdWString());

    IRevisionCloud* pRevisionCloud = GetSelectedElement(m_pDocument);
    if (pRevisionCloud == nullptr)
    {
        return;
    }
    pRevisionCloud->SetTypeId(typeId);
}

void RevisionCloudStyleDlg::OnComponentTypeAddButtonClick()
{
    auto funGetName = [this](const std::wstring& strCurrentName)->std::wstring
    {
        QDialog dlgCreateName(this);
        dlgCreateName.setWindowTitle(QString::fromLocal8Bit("请输入新的名称"));
        QLineEdit lineEdit(&dlgCreateName);
        lineEdit.setText(QString::fromStdWString(strCurrentName));
        dlgCreateName.exec();
        return lineEdit.text().toStdWString();
    };

    gcmp::IRevisionCloudStyleManager* pStyleMgr = gcmp::IRevisionCloudStyleManager::Get(m_pDocument);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pStyleMgr != nullptr, L"云线的样式管理为空",L"GDMPLab",L"2024-03-30");
    const std::wstring strCurrentName = pStyleMgr->GetCurrentStyleType();
    ElementId currentId = pStyleMgr->FindStyleType(strCurrentName);

    std::wstring strNewName = L"";
    while (strNewName.empty())
    {
        std::wstring strRet = funGetName(strCurrentName);
        std::vector<std::wstring> allTypeNames = pStyleMgr->GetAllStyleTypeNames();
        auto iter = std::find(allTypeNames.begin(), allTypeNames.end(), strRet);
        if (iter == allTypeNames.end())
        {
            strNewName = strRet;
        }
        else
        {
            QMessageBox::information(this,QString(),QString::fromLocal8Bit("名称重复,请重新输入"));
        }
    }


    DetailStyleDialog detailStyleDialog;
    detailStyleDialog.setValue(m_ui.lineEditLoop->text(),
        m_ui.lineEditAnnatation->text(),
        m_ui.lineEditVersion->text(),
        m_ui.lineEditLinewire->text());
    if (detailStyleDialog.exec() != QDialog::Accepted)
    {
        return;
    }
    
   
    const IGenericType* pGenericType = quick_cast<IGenericType>(m_pDocument->GetElement(currentId));
    DBG_WARN_AND_RETURN_VOID_UNLESS(pGenericType != nullptr, L"pGenericType为空",L"GDMPLab",L"2024-03-30");
    const IElementCopyPasteComponent* pCopyPasteComponent = pGenericType->GetCopyPasteComponent();
    std::wstring strError;
    if (!pCopyPasteComponent->CanBeCopied(&strError))
    {
        return;
    }

    OwnerPtr<IUserTransaction> ut = IUserTransaction::Create(m_pDocument, GBMP_TR(L"复制"));
    DBG_WARN_AND_RETURN_VOID_UNLESS(ut != nullptr, L"事务创建不成功",L"GDMPLab",L"2024-03-30");

    const ICopyOperator* pDefaultCopyOperator = ICopyOperator::Get();
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDefaultCopyOperator != nullptr, L"默认的拷贝器不应该为空",L"GDMPLab",L"2024-03-30");
    std::vector<ElementId> arrCopyIds = {currentId};
    const std::vector<ElementId>& retCopy = pDefaultCopyOperator->CopyElements(m_pDocument, arrCopyIds, std::map<ElementId, ElementId>(), nullptr);
    IGenericType* pGenericTypeNew = quick_cast<IGenericType>(m_pDocument->GetElement(retCopy[0]));
    pGenericTypeNew->GetBasicInformation()->SetName(strNewName);
    pStyleMgr->AddCloudStypeType(retCopy[0]);
    pStyleMgr->SetCurrentStyleType(strNewName);

    QString strStyleLoop;
    QString strStyleAnnotation;
    QString strStyleVersion;
    QString strStyleLinewire;
    detailStyleDialog.GetValue(strStyleLoop, strStyleAnnotation, strStyleVersion, strStyleLinewire);
    pStyleMgr->UpdateAnnotationStype(strStyleAnnotation.toStdWString());
    pStyleMgr->UpdateVersionStyle(strStyleVersion.toStdWString());
    
    ut->Commit();

    m_ui.comboBoxType->addItem(QString::fromStdWString(strNewName));
    m_ui.comboBoxType->setCurrentText(QString::fromStdWString(strNewName));
}

void RevisionCloudStyleDlg::InitStyles()
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pDocument != nullptr, L"文档为空",L"GDMPLab",L"2024-03-30");
    const gcmp::IRevisionCloudStyleManager* pStyleMgr = gcmp::IRevisionCloudStyleManager::Get(m_pDocument);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pStyleMgr != nullptr, L"云线的样式管理为空",L"GDMPLab",L"2024-03-30");
    
    std::vector<std::wstring> arrTypeNames = pStyleMgr->GetAllStyleTypeNames();
    QStringList listName;
    for (auto& var:arrTypeNames)
    {
        listName.append(QString::fromStdWString(var));
    }
    m_ui.comboBoxType->addItems(listName);  
    m_ui.comboBoxType->setCurrentText(QString::fromStdWString(pStyleMgr->GetCurrentStyleType()));
    onTypeChanged(m_ui.comboBoxType->currentText());
}

void RevisionCloudStyleDlg::InitSetElementType(gcmp::IDocument*pDoc)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(m_pDocument != nullptr, L"文档为空",L"GDMPLab",L"2024-03-30");
    const gcmp::IRevisionCloudStyleManager* pStyleMgr = gcmp::IRevisionCloudStyleManager::Get(m_pDocument);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pStyleMgr != nullptr, L"云线的样式管理为空",L"GDMPLab",L"2024-03-30");

    std::vector<std::wstring> arrTypeNames = pStyleMgr->GetAllStyleTypeNames();
    QStringList listName;
    for (auto& var : arrTypeNames)
    {
        listName.append(QString::fromStdWString(var));
    }

    m_ui.comboBoxTypeSelect->addItems(listName);
    IRevisionCloud* pRevisionCloud = GetSelectedElement(pDoc);
    if (pRevisionCloud != nullptr)
    {
        const IRevisionCloudType* pType = pRevisionCloud->GetType();
        m_ui.comboBoxTypeSelect->setCurrentText(QString::fromStdWString(pType->GetOwnerElement()->GetBasicInformation()->GetName()));
    }
}

IRevisionCloud* RevisionCloudStyleDlg::GetSelectedElement(gcmp::IDocument*pDoc)
{
    std::vector<ElementId> selElements;

    //多选Element
    const GraphicsNodeReferenceOwnerPtrSet& nodeRefs = ISelection::Get()->GetGraphicsNodeReferences();
    FOR_EACH(selItem, nodeRefs)
    {
        ElementId selectedId = selItem->GetElementId();
        selElements.push_back(selectedId);
    }

    if (selElements.size() == 0)
    {
        return nullptr;
    }
    
    IElement* pElement = pDoc->GetElement(selElements[0]);
    if (pElement == nullptr)
    {
        return nullptr;
    }
    IGenericElement* pGenericElement = quick_cast<IGenericElement>(pElement);
    if (pGenericElement == nullptr)
    {
        return nullptr;
    }
    IExternalObject* pExternalObject = pGenericElement->GetExternalObject();
    if (pExternalObject == nullptr)
    {
        return nullptr;
    }
    return quick_cast<IRevisionCloud>(pExternalObject);
}
